package crypto

import (
	"crypto/rand"
	"encoding/hex"
	"strings"

	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/errors/gerror"
)

// GenerateSalt 生成随机盐值
func GenerateSalt() (string, error) {
	salt := make([]byte, 16)
	if _, err := rand.Read(salt); err != nil {
		return "", gerror.Wrap(err, "生成盐值失败")
	}
	return hex.EncodeToString(salt), nil
}

// HashPassword 加密密码
func HashPassword(password, salt string) string {
	// 将密码和盐值组合
	combined := password + salt
	
	// 使用MD5进行多次加密提高安全性
	hash1 := gmd5.MustEncrypt(combined)
	hash2 := gmd5.MustEncrypt(hash1 + salt)
	
	return hash2
}

// GeneratePasswordHash 生成密码散列（包含盐值）
func GeneratePasswordHash(password string) (string, error) {
	if password == "" {
		return "", gerror.New("密码不能为空")
	}
	
	// 生成盐值
	salt, err := GenerateSalt()
	if err != nil {
		return "", err
	}
	
	// 加密密码
	hashedPassword := HashPassword(password, salt)
	
	// 返回格式: 盐值$散列值
	return salt + "$" + hashedPassword, nil
}

// VerifyPassword 验证密码
func VerifyPassword(password, hashedPassword string) bool {
	if password == "" || hashedPassword == "" {
		return false
	}
	
	// 检查是否是新格式（包含$分隔符）
	if strings.Contains(hashedPassword, "$") {
		// 新的加密方式
		return verifyNewFormat(password, hashedPassword)
	} else {
		// 简化的加密方式（兼容默认管理员）
		return verifySimpleFormat(password, hashedPassword)
	}
}

// verifyNewFormat 验证新格式密码
func verifyNewFormat(password, hashedPassword string) bool {
	// 分离盐值和散列值
	parts := []byte(hashedPassword)
	var salt, hash string
	
	// 查找$分隔符
	for i, b := range parts {
		if b == '$' && i < len(parts)-1 {
			salt = string(parts[:i])
			hash = string(parts[i+1:])
			break
		}
	}
	
	if salt == "" || hash == "" {
		return false
	}
	
	// 使用相同方法加密输入密码
	inputHash := HashPassword(password, salt)
	
	// 比较散列值
	return inputHash == hash
}

// verifySimpleFormat 验证简化格式密码（兼容默认管理员）
func verifySimpleFormat(password, hashedPassword string) bool {
	// 使用固定盐值加密
	salt := "goldtree_salt"
	combined := password + salt
	inputHash := gmd5.MustEncrypt(combined)
	
	return inputHash == hashedPassword
}

// ValidatePasswordStrength 验证密码强度
func ValidatePasswordStrength(password string) error {
	if len(password) < 6 {
		return gerror.New("密码长度不能少于6位")
	}
	
	if len(password) > 32 {
		return gerror.New("密码长度不能超过32位")
	}
	
	// 检查是否包含字母和数字
	hasLetter := false
	hasDigit := false
	
	for _, char := range password {
		if char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' {
			hasLetter = true
		} else if char >= '0' && char <= '9' {
			hasDigit = true
		}
		
		if hasLetter && hasDigit {
			break
		}
	}
	
	if !hasLetter {
		return gerror.New("密码必须包含字母")
	}
	
	if !hasDigit {
		return gerror.New("密码必须包含数字")
	}
	
	return nil
}